package com.niit.controller;

import com.alibaba.nacos.shaded.com.google.common.base.Strings;
import com.niit.apis.UserFeignApi;
import com.niit.entity.*;
import com.niit.entity.dto.InfoUpdateDTO;
import com.niit.entity.dto.LoginAccountDTO;
import com.niit.entity.dto.UserDisplayDTO;
import com.niit.utils.CompanyQueryApi;
import com.niit.utils.FileHashCal;
import com.niit.utils.Result;
import com.niit.utils.exception.SystemControllerException;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;

import static com.niit.utils.FileHashCal.NormalConfig.avatarDir;
import static com.niit.utils.FileHashCal.NormalConfig.resumeDir;

@RestController
public class UserController {
	private final UserFeignApi userFeignApi;

	public UserController(UserFeignApi userFeignApi) {
		this.userFeignApi = userFeignApi;
	}

	@RestController
	@RequestMapping("/api/account")
	public static class AccountController{
		@Autowired
		private UserFeignApi userFeignApi;

		@PostMapping("/login")
		public Result<Object> login(
				HttpSession session,
				@RequestParam String phone,
				@RequestParam String password,
				@RequestParam(required = false, defaultValue = "1") Integer loginType
		){
			LoginAccountDTO login = userFeignApi.login(phone, password, loginType);
			if(login.getStatus() == HttpStatus.OK.value()){
				Info info = new Info();
				if(login.getUser() != null) {
					session.setAttribute("account", login.getUser());
					info = login.getUser().getInfo();
				}
				if(login.getAdmin() != null) {
					session.setAttribute("account", login.getAdmin());
					info = login.getAdmin().getInfo();
				}
				if(info.getAvatarHash() != null) {
					String base64 = FileHashCal.turnToBase64(info.getAvatarHash());
					if(base64 != null) session.setAttribute("avatarBase64", base64);
				}
				session.setAttribute("loginType", loginType);
			}
			return Result.success(login.getStatus(), login.getMsg());
		}

		@PostMapping("/register")
		public Result<Object> register(
				@RequestParam String phone,
				@RequestParam String password,
				@RequestParam(required = false, defaultValue = "1") Integer registerType
		){
			return userFeignApi.register(phone, password, registerType);
		}

		@PostMapping("/logout")
		public Result<Object> logout(HttpSession session){
			Object account = session.getAttribute("account");
			LoginAccountDTO loginAccountDTO = new LoginAccountDTO();
			if(account instanceof Admin admin){
				loginAccountDTO.setAdmin(admin);
			}else if(account instanceof User user){
				loginAccountDTO.setUser(user);
			}
			Result<Object> logout = userFeignApi.logout(loginAccountDTO);
			session.invalidate();
			return logout;
		}
		@PostMapping("/infoUpdate")
		public Result<Object> info(
				@Validated InfoUpdateDTO infoUpdateDTO,
				HttpSession session) {
			if(infoUpdateDTO.getPhone() == null || infoUpdateDTO.getPhone().isEmpty()) throw new SystemControllerException("手机号异常");
			if(infoUpdateDTO.getUsername() == null || infoUpdateDTO.getUsername().isEmpty()) throw new SystemControllerException("用户名异常");
			Object account = session.getAttribute("account");
			Integer loginType = (Integer) session.getAttribute("loginType");
			Integer id = loginType == 3 ? ((Admin)account).getId() : ((User)account).getId();
			Info info = userFeignApi.getUser(id).getInfo();
			info.setAddressDetail(infoUpdateDTO.getAddressDetail());
			info.setEmail(infoUpdateDTO.getEmail());
			info.setPhone(infoUpdateDTO.getPhone());
			info.setUsername(infoUpdateDTO.getUsername());
			info.setBirthday(infoUpdateDTO.getBirthday());
			info.setGender(infoUpdateDTO.getGender());
			info.setEmail(infoUpdateDTO.getEmail());
			info.setDescription(infoUpdateDTO.getDescription());
			info.setRealName(infoUpdateDTO.getRealName());
			info.setIdCard(infoUpdateDTO.getIdCard());
			if(infoUpdateDTO.getRegion().getCode() != null){
				Region region = userFeignApi.getRegion(infoUpdateDTO.getRegion().getCode());
				info.setRegion(region);
			}

			String avatarHash = FileHashCal.getHashAndSave(infoUpdateDTO.getAvatar(), avatarDir);
			if(avatarHash != null) {
				info.setAvatarHash(avatarHash);
				String base64 = FileHashCal.turnToBase64(info.getAvatarHash());
				if(base64 != null) session.setAttribute("avatarBase64", base64);
			}
			Info updateInfo = userFeignApi.saveInfo(info);
			LoginAccountDTO loginAccountDTO = new LoginAccountDTO();
			if(updateInfo != null){
				if(loginType == 3) {
					loginAccountDTO.setAdmin((Admin) account);
					loginAccountDTO.getAdmin().setInfo(updateInfo);
				} else {
					User user = (User) account;
					loginAccountDTO.setUser(user);
					loginAccountDTO.getUser().setInfo(updateInfo);
					String resumeHash = FileHashCal.getHashAndSave(infoUpdateDTO.getResumeFile(), resumeDir);
					if(resumeHash != null) user.setResumeHash(resumeHash);
					userFeignApi.updateUser(user);
					session.setAttribute("account", user);
				}
			}
			Integer companyId = infoUpdateDTO.getCompanyId();
			if(companyId != null){
				Company company = userFeignApi.getCompany(companyId);
				if(company != null && account instanceof User user){
					User user1 = userFeignApi.getUser(user.getId());
					user1.setCompany(company);
					userFeignApi.updateUser(user1);
				}
			}

			return Result.success();
		}

		@PostMapping("/getAllUser")
		public Result<?> getAllUser(
				@RequestParam(required = false) String phone,
				@RequestParam(required = false) String username,
				@RequestParam(required = false) String realName,
				@RequestParam(required = false) String gender,
				@RequestParam(required = false) Boolean userType,
				@RequestParam(defaultValue = "1") Integer page,
				@RequestParam(defaultValue = "10") Integer size
		){
			phone = Strings.emptyToNull(phone);
			username = Strings.emptyToNull(username);
			realName = Strings.emptyToNull(realName);
			gender = Strings.emptyToNull(gender);
			Page<User> allUser = userFeignApi.getAllUser(phone, username, realName, gender, userType, page, size);
			List<User> content = allUser.getContent();
			List<UserDisplayDTO> userDisplayDTOList = content.stream().map(user -> {
				String avatarHash = user.getInfo().getAvatarHash();
				UserDisplayDTO userDisplayDTO = new UserDisplayDTO(user, null);
				if(avatarHash != null) {
					String base64 = FileHashCal.turnToBase64(avatarHash);
					if(base64 != null) userDisplayDTO.setAvatarBase64(base64);
					return userDisplayDTO;
				}
				return userDisplayDTO;
			}).toList();
			return Result.successPage(userDisplayDTOList, allUser.getTotalElements()).code(200);
		}

		@DeleteMapping("/deleteUser/{id}")
		public Result<?> deleteUser(@PathVariable Integer id){
			userFeignApi.deleteUserById(id);
			return Result.success();
		}

		@GetMapping("/downloadResume/{id}")
		public void downloadResume(@PathVariable Integer id, HttpServletResponse response){
			User user = userFeignApi.getUser(id);
			if(user != null){
				String resumeHash = user.getResumeHash();
				if(resumeHash != null){
					File file = new File(resumeDir + File.separator + resumeHash);
					try (InputStream is = new FileInputStream(file); OutputStream os = response.getOutputStream()){
						if(!file.exists()) {
							response.sendError(HttpStatus.NOT_FOUND.value(), "文件不存在");
							return;
						}
						response.setContentType("application/octet-stream");
						response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(user.getInfo().getUsername() + ".pdf", StandardCharsets.UTF_8));
						response.setContentLengthLong(file.length());
						byte[] buffer = new byte[1024];
						int bytesRead;
						while ((bytesRead = is.read(buffer)) != -1) {
							os.write(buffer, 0, bytesRead);
						}
						os.flush();
					}catch (Exception ignored){}
				}
			}
		}

		@PostMapping("/updateUser")
		public Result<?> updateUser(@RequestBody User user){
			User updateUser = userFeignApi.updateUser(user);
			return Result.success();
		}
	}

	@RestController
	@RequestMapping("/api/region")
	public static class RegionController{
		@Autowired
		private UserFeignApi userFeignApi;

		@PostMapping("/findRegion")
		public ResponseEntity<List<Region>> findRegion(@RequestBody Region region){
			List<Region> regions = userFeignApi.findRegion(region);
			if(regions != null) return ResponseEntity.ok(regions);
			else return ResponseEntity.notFound().build();
		}

		@PostMapping("/findRegionByLevel")
		public ResponseEntity<List<Region>> findRegionByLevel(@RequestParam(defaultValue = "1") Byte level){
			List<Region> regions = userFeignApi.findRegionByLevel(level);
			if(regions != null) return ResponseEntity.ok(regions);
			else return ResponseEntity.notFound().build();
		}
	}

	@RestController
	@RequestMapping("/api/company")
	public static class CompanyController{
		@Autowired
		private UserFeignApi userFeignApi;

		@PostMapping("/add")
		public Result<?> addCompany(@RequestBody Company company){
			if(company.getCompanyName() == null) return Result.error("未输入企业名").code(404);
			Company queryApiCompany = CompanyQueryApi.apiCompany(company.getCompanyName());
			if (queryApiCompany != null) {
				Region adCode = userFeignApi.getRegion(queryApiCompany.getAddressRegion().getCode());
				queryApiCompany.setAddressRegion(adCode);
			}else return Result.error("不存在该企业或查询错误，请检查企业名").code(404);
			userFeignApi.addCompany(queryApiCompany);
			return Result.success();
		}

		@PostMapping("/delete/{id}")
		public Result<?> deleteCompany(@PathVariable Integer id){
			userFeignApi.deleteCompany(id);
			return Result.success();
		}

		@GetMapping("/list")
		public Result<?> listCompany(
				@RequestParam(defaultValue = "1") Integer page,
				@RequestParam(defaultValue = "10") Integer size,
				@RequestParam(required = false) String companyName
		){
			Page<Company> companyList = userFeignApi.getCompanyList(page, size, companyName);
			return Result.successPage(companyList.getContent(), companyList.getTotalElements()).code(200);
		}

		@PostMapping("/getAll")
		public Result<?> getAllCompany(){
			List<Company> companyList = userFeignApi.getAllCompany();
			return Result.success(companyList);
		}
	}

	@RestController
	@RequestMapping("/api/info")
	public static class InfoController{
		@Autowired
		private UserFeignApi userFeignApi;

		@PostMapping("/getAll")
		public Result<?> getAllInfos(
				@RequestParam(required = false) String phone,
				@RequestParam(required = false) String username,
				@RequestParam(required = false) String realName,
				@RequestParam(required = false) String status,
				@RequestParam(defaultValue = "1") Integer page,
				@RequestParam(defaultValue = "10") Integer size
		){
			phone = Strings.emptyToNull(phone);
			username = Strings.emptyToNull(username);
			realName = Strings.emptyToNull(realName);
			status = Strings.emptyToNull(status);
			Page<Info> allInfos = userFeignApi.getAllInfos(phone, username, realName, status, page, size);
			return Result.successPage(allInfos.getContent(), allInfos.getTotalElements()).code(200);
		}

		@PostMapping("/delete/{id}")
		public Result<?> deleteInfo(@PathVariable Integer id){
			userFeignApi.deleteInfo(id);
			return Result.success();
		}
	}
}
